home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
SGI Developer Toolbox 6.1
/
SGI Developer Toolbox 6.1 - Disc 4.iso
/
public
/
bit
/
src
/
marking.c
< prev
next >
Wrap
C/C++ Source or Header
|
1994-08-01
|
44KB
|
1,733 lines
/*
* $Id: marking.c,v 0.91 1994/02/20 00:53:16 zhao Pre-Release $
*
*. This file is part of BIT shareware package. After the two weeks of
* free evaluation period, you are encouraged (required) to register
* your copy for a small registration fee, which is $35 for personal use
* and $50 for commercial, government and institutional use.
*
* Copyright(c) 1993, 1994 by T.C. Zhao.
* All rights reserved.
*
* Permission to use, copy, and distribute this software in its entirety
* for non-commercial purposes is hereby granted, provided that the
* above shareware and copyright notices and this permission notice
* appear in all copies and their documentation.
*
* This software may be modified for your own use, but modified versions
* may not be distributed without prior consent of the author.
*
* This software is provided "as is" without expressed or implied
* warranty of any kind.
*
*.
*
* Purpose:
* Place various simple geometric figures into image. The bitmaps is
* in bm.h while the actual drawing routine in gl_util.c and ps.c.
* It is sort of bad that all locations refers to the CENTER of the
* sgfs and NOT the lower left corner.
*
* Code is a little more complicated than it should be because
* doublebuffering in over/pup is generally not supported in hardware.
* Need to simulate it. It appear working ok, but speed is not too good.
*/
#if !defined(lint) && defined(F_ID)
char *id_mk = "$Id: marking.c,v 0.91 1994/02/20 00:53:16 zhao Pre-Release $";
#endif
#include "bit.h"
#include "extern.h"
#include "bm.h" /* the bitmaps. */
/******************* Limits and defines **********************/
/********************************************************
* If NO_OP_DBL is defined, double buffer simulation in
* over/pup plane will be suppressed.
********************************************************/
/* #define NO_OP_DBL */
#define MAXOBJS 25 /* max no. of different objects */
#define MAXOSIZE 600 /* max size of the objects */
#define MAXSAVE 101 /* max no. of objs per image */
/*************** Local varialbes, excluding GUI *************/
static float mapx = 1.0, mapy = 1.0;
static int pixels = 1; /* units of measurement */
static int orix, oriy; /* origin of measurement */
static int x, y; /* position relative to window */
static int w = 20, h = 20; /* current size in pixels */
static int angle, langle; /* angle of rotation, deci-degree */
static int lx, ly, lw, lh; /* last position and size */
static int lwidth = 1; /* line width */
static int llwidth = 1; /* line width */
static int bcolor = 1; /* over/pup index used */
static int xy = 1; /* if keep aspect ratio */
static int reportr; /* distance reporting */
static int immediate = 1; /* rendering method */
/* Default color */
static int dcol[] =
{
0xff, 0xff, 0, 0
};
/*********** local functions and structures *******************/
typedef void (*GL_draw) (int, int, int, int, int, int);
typedef const char *PS_draw;
static void mark_move(void);
static void mark_moving(long);
static void mark_events(IPTR, long, short);
static int mark_wm_event(IPTR, int);
static void mark_draw(int, int);
static void mark_doit(IPTR, int, int, int, int);
/* Structure for simple geometric figures */
typedef struct
{
const char *name; /* name. Must not be null */
char *bits; /* bitmaps for the sgf */
GL_draw how; /* GL drawing routine */
const char *psdraw; /* PS drawing commands */
int fill; /* If filled sgf */
}
Obj_t;
/**************************************************************/
/* all PostScript drawings are defined in ps.c. */
extern const char ps_plus[];
extern const char ps_circ[], ps_rect[];
extern const char ps_tri[], ps_star[];
extern const char ps_arrow[], ps_hdist[], ps_line[];
/****** All objects definations ********************************/
static const Obj_t objs[] =
{
{"Plus", plus_bits, gl_plus, ps_plus, 0}, /* plus */
{"Hdist", hdist_bits, gl_hdist, ps_hdist, 0}, /* |---| */
{"Delta", tri_bits, gl_tri, ps_tri, 0}, /* triangle */
{"DeltaF", ftri_bits, gl_tri, ps_tri, 1}, /* filled */
{"Circ", circ_bits, gl_circ, ps_circ, 0}, /* circle */
{"CircF", fcirc_bits, gl_circ, ps_circ, 1}, /* filled */
{"Rect", rect_bits, gl_rect, ps_rect, 0}, /* rectangle */
{"RectF", frect_bits, gl_rect, ps_rect, 1}, /* filled */
{"Star", star_bits, gl_star, ps_star, 0},
{"StarF", fstar_bits, gl_star, ps_star, 1},
{"Arrow", arrow_bits, gl_arrow, ps_arrow, 1},
{"Line", line_bits, gl_line, ps_line, 0}
};
static int totalobjs = sizeof(objs) / sizeof(objs[0]);
static int currentobj, cfill;
static GL_draw cdraw; /* curerent drawing routine */
/*********** GUI stuff ***************************************/
static FL_FORM *tobj;
/* create the forms containing bitmaps for the symbols */
static void create_form_tobj(void);
static void handle_bmcb(FL_OBJECT * ob, long p);
static void save_it(int, int, int, int, int, int, rgba_t, ci_t);
static void show_map_unit(float, float);
static void report_distance(int, int);
static void report_size(int, int);
static void report_rotation(float);
static void save_bcolor(void);
static void restore_bcolor(void);
static void origin_cb(FL_OBJECT *, long);
static void map_slider(void);
/********************************************************************
* non-interactively set origin. Always relative to ll corner of img
**********************************************************************/
static int niorix, nioriy;
void
set_marking_origin(int ox, int oy)
{
niorix = ox;
nioriy = oy;
}
/***********************************************************************
* mark specific position within the image with simple geometric figures
* Global entry point
************************************************************************/
int
img_marking(IPTR im)
{
short val;
long dev;
cdraw = objs[currentobj].how;
cfill = objs[currentobj].fill;
if (bcolor >= over_pup_colors)
bcolor = over_pup_colors - 1;
if (bcolor == 0) /* avoid interference with WM */
bcolor = 1;
save_bcolor();
set_use_calloc(1);
/* how to handle window resize, repositioning */
install_wm_handler(mark_wm_event);
/* initialize position */
mark_wm_event(im, 0);
create_form_tobj();
show_map_unit(mapx, mapy);
/* do this to get origin right */
x = niorix + im->xi;
y = nioriy + im->yi;
origin_cb(0, 0);
bit_show_form(tobj, FL_PLACE_MOUSE, 0, "Objects");
handle_bmcb(0, currentobj);
mark_draw(currentobj, bcolor);
report_distance(x, y);
while ((dev = bit_qread(&val)) != KEYBD || val != 27)
mark_events(im, dev, val);
/* done. Clean up */
clear_over_pup();
remove_wm_handler(mark_wm_event);
bit_hide_form(tobj);
set_current_window(win_id);
drawmode(NORMALDRAW);
linewidth(1); /* line width is shared among all buffers */
restore_bcolor();
hide_rect_size();
hide_mouse_position();
set_use_calloc(0);
hide_getcolor();
return 0;
}
/*********************************************************
* Save current position
*********************************************************/
static void
save_position(void)
{
lx = x;
ly = y;
lw = w;
lh = h;
llwidth = lwidth;
langle = angle;
}
/**********************************************************
* given a name, find index
************************************************************/
static int
sgf_get_index(const char *p)
{
int i, k;
if (!p || !*p)
return 0;
for (i = k = 0; !k && i < totalobjs; i++)
k = strcmp(objs[i].name, p) == 0;
return k ? --i : 0;
}
/**********************************************************
* Global routine that set the units of measure
***********************************************************/
void
set_marking_units(float mx, float my)
{
if (mx > 0.0)
mapx = mx;
if (my > 0.0)
mapy = my;
}
/******************************************************************
* Clear up the old one and draw a new one. No set_current_windows, no
* buffer switch etc.
*****************************************************************/
static void
mark_draw_only(int ind, int bc)
{
static int lastind;
int noclear;
/* if same object but larger, there is no need to clear screen. */
noclear = (ind == lastind) &&
(langle == angle) &&
(lwidth >= llwidth) &&
(lx == x) && (ly == y) && (lw <= w) && (lh <= h) && cfill;
/* arrow is a special case: it has cfill but not really filled */
if (!noclear || cdraw == gl_arrow)
{
color(0);
cdraw(lx, ly, lw, lh, cfill, langle);
currentobj = ind;
cfill = objs[ind].fill;
cdraw = objs[ind].how;
}
lastind = ind;
/* draw the new one */
color(bc);
cdraw(x, y, w, h, cfill, angle);
save_position();
}
#ifndef NO_OP_DBL
static void mark_rasterize(void);
#else
#define mark_rasterize()
#endif
/**********************************************************************
* Draw the current object in the over/pup plane and taking care of
* window and framebuffer as well
*********************************************************************/
static void
mark_draw(int ind, int bc)
{
long owin = winget();
set_current_window(win_id);
reshapeviewport();
switch_frame_buffer();
linewidth(lwidth);
mark_draw_only(ind, bc);
mark_rasterize();
set_current_window(win_id);
reshapeviewport();
drawmode(NORMALDRAW);
set_current_window(owin);
}
/*******************************************************************
* Do a complete draw after refreshing over/pup plane
*******************************************************************/
static void
complete_draw(int ind, int bc)
{
clear_over_pup();
set_current_window(win_id);
switch_frame_buffer();
linewidth(lwidth);
currentobj = ind;
cfill = objs[ind].fill;
cdraw = objs[ind].how;
color(bc);
cdraw(x, y, w, h, cfill, angle);
mark_rasterize();
save_position();
set_current_window(win_id);
drawmode(NORMALDRAW);
}
/************************************************************
* handle window re-size and reposition events
*************************************************************/
static int
mark_wm_event(IPTR im, int wm)
{
static int imxi, imyi;
if (!wm)
{
x = lx = (im->xi > 0) ? im->xi : 1;
y = ly = (im->yi > 0) ? im->yi : 1;
if (IS_CI(im))
{
dcol[3] = im->cmap->colors - 2;
dcol[0] = im->cmap->ct[0][dcol[3]];
dcol[1] = im->cmap->ct[1][dcol[3]];
dcol[2] = im->cmap->ct[2][dcol[3]];
}
}
else
{
/* x and y must be unchanged relative to image */
x += (im->xi - imxi);
y += (im->yi - imyi);
complete_draw(currentobj, bcolor);
}
imxi = im->xi;
imyi = im->yi;
return 0;
}
/*****************************************************************
* How to handle keyboad events
****************************************************************/
static long
mark_keybd(int val)
{
int ret = 0;
static int step = 1;
int re_ras = 0; /* if re-rasterize the object */
switch (val)
{
case 'r':
angle -= step * 10;
if (angle < -3600)
angle += 3600;
re_ras = 1;
break;
case 'R':
angle += step * 10;
if (angle > 3600)
angle -= 3600;
re_ras = 1;
break;
case 'x':
if ((w -= step) < 1)
w = 1;
re_ras = 1;
break;
case 'X':
if ((w += step) > MAXOSIZE)
w = MAXOSIZE;
re_ras = 1;
break;
case 'y':
if ((h -= step) < 1)
h = 1;
re_ras = 1;
break;
case 'Y':
if ((h += step) > MAXOSIZE)
h = MAXOSIZE;
re_ras = 1;
break;
case 'h':
case 'H':
x -= step;
break;
case 'L':
case 'l':
x += step;
break;
case 'j':
case 'J':
y -= step;
break;
case 'K':
case 'k':
y += step;
break;
default:
if (val > '0' && val <= '9')
step = val - '0';
else
ret = val;
break;
}
if (re_ras)
{
mark_draw(currentobj, bcolor);
report_rotation(0.1 * angle);
report_size(w, h);
}
else
mark_move();
return ret;
}
/***********************************************************************
* All GL events
*********************************************************************/
/* ARGSUSED */
static void
mark_events(IPTR im, long dev, short val)
{
switch (dev)
{
case KEYBD:
mark_keybd(val);
break;
case UPARROWKEY:
if (val)
mark_keybd('k');
break;
case DOWNARROWKEY:
if (val)
mark_keybd('j');
break;
case LEFTARROWKEY:
if (val)
mark_keybd('h');
break;
case RIGHTARROWKEY:
if (val)
mark_keybd('l');
break;
case LEFTMOUSE:
case MIDDLEMOUSE:
if (val)
mark_moving(dev);
break;
default:
break;
}
}
#ifdef NO_OP_DBL
#define dbl_mark_move sgl_mark_move
#define dbl_mark_moving sgl_mark_moving
#else
/*****************************************************************
* Get current object in rasterized form.
* feedback should be the way to get the rasterized object, but it
* is not portable, too lazy to do it. Cheat here
******************************************************************/
static ci_t **cfig;
static int objbw, objbh;
static void
mark_rasterize(void)
{
int bx, by, bw, bh;
register ci_t *s;
static int lastrasw, lastrash, lastlwidth;
static int lastrotate;
static GL_draw lastdraw;
static int incomplete;
int halflw = (lwidth + 1) / 2;
int sameobj, openobj;
if (!simu_op_dblbuf)
return;
/* check if same object */
sameobj = (lastlwidth == lwidth) &&
(lastrotate == angle) &&
(lastrasw == w && lastrash == h) &&
(lastdraw == cdraw);
openobj = (cfill == 0 || cdraw == gl_arrow);
if ((openobj || sameobj) && !incomplete)
return;
find_bbox(x - halflw, y - halflw, w + (lwidth + 1), h + (lwidth + 1),
0.1 * angle, &bx, &by, &bw, &bh);
bh += lwidth + 1;
bw += lwidth + 1;
/* it is important to center (x,y) */
bx = x - (bw / 2);
by = y - (bh / 2);
/* get buffer for the rasterized object */
if (cfig)
free_mat(cfig);
cfig = get_mat(bh, bw, sizeof(**cfig));
rectread(bx, by, bx + bw - 1, by + bh - 1, cfig[0]);
incomplete = (bx <= 0 || (bx + bw - 1) >= win_w ||
(by <= 0 || (by + bh - 1) >= win_h));
/* mask off the garbarge */
s = cfig[0] + bw * bh;
while (--s >= cfig[0])
*s = ((*s & bcolor) != bcolor) ? 0 : bcolor;
objbw = bw;
objbh = bh;
lastrasw = w;
lastrash = h;
lastdraw = cdraw;
lastrotate = angle;
lastlwidth = lwidth;
#ifdef MDEBUG
M_debug("MarkRasterize", "Done");
#endif
}
/****************************************************************
* Move mark without flickering, i.e., simulating double buffering.
* Doesn't take care window, buffer etc.
* (x,y) new location
****************************************************************/
static void
dbl_mark_move(void)
{
int x1, x2, y1, y2;
static ci_t **scrn;
int sw, sh;
int halfw = objbw / 2 + 1, halfh = objbh / 2 + 1;
x1 = Min(lx, x) - 1;
x2 = Max(lx, x) + 1;
y1 = Min(ly, y) - 1;
y2 = Max(ly, y) + 1;
sw = x2 - x1 + 1 + objbw + 2;
sh = y2 - y1 + 1 + objbh + 2;
(report_mouse ? show_mouse_position : report_distance) (x, y);
if (scrn)
free_mat(scrn);
scrn = get_mat(sh, sw, sizeof(ci_t));
put_submat(scrn, sh, sw, cfig, (y - y1) + 1, (x - x1) + 1,
objbh, objbw, sizeof(ci_t));
x1 -= halfw;
y1 -= halfh;
rectwrite(x1, y1, x1 + sw - 1, y1 + sh - 1, scrn[0]);
save_position();
}
/********************************************************************
* Simulate a double buffer in over/pup plane
*******************************************************************/
static void
dbl_mark_moving(long dev)
{
do
{
get_mouse(&x, &y);
x -= win_xo;
y -= win_yo;
if (lx - x || ly - y)
dbl_mark_move();
}
while (getbutton(dev));
#ifdef MDEBUG
M_debug("MoveMark", "Simulated doublebuffer");
#endif
}
#endif /* NO_OP_DBL */
/***********************************************************
* Continuously move mark as long as mouse is down
***********************************************************/
static void
sgl_mark_move(void)
{
/* draw it will set lx, ly */
mark_draw_only(currentobj, bcolor);
(report_mouse ? show_mouse_position : report_distance) (x, y);
}
static void
sgl_mark_moving(long dev)
{
do
{
get_mouse(&x, &y);
x -= win_xo;
y -= win_yo;
if (x - lx || y - ly)
{
(report_mouse ? show_mouse_position : report_distance) (x, y);
mark_draw(currentobj, bcolor);
}
}
while (getbutton(dev));
#ifdef MDEBUG
M_debug("MoveMark", "single");
#endif
}
/*************************************************************
* Dragging the current object
*************************************************************/
static void
mark_moving(long dev)
{
/* another chance to re-rasterize */
get_mouse(&x, &y);
x -= win_xo;
y -= win_yo;
mark_draw(currentobj, bcolor);
set_current_window(win_id);
switch_frame_buffer();
((cfill && cdraw != gl_arrow && simu_op_dblbuf && cfig) ?
dbl_mark_moving : sgl_mark_moving) (dev);
set_current_window(win_id);
drawmode(NORMALDRAW);
}
/******************************************************************
* move current object to a new location
******************************************************************/
static void
mark_move(void)
{
set_current_window(win_id);
switch_frame_buffer();
((cfill && simu_op_dblbuf) ? dbl_mark_move : sgl_mark_move) ();
drawmode(NORMALDRAW);
}
static FL_OBJECT *bms[MAXOBJS], *hb[MAXOBJS], *sl[2];
static FL_OBJECT *otext, *rtext, *dtext;
static int totalshown, offset;
static FL_OBJECT *ix, *iy, *mxi, *myi, *ingrp;
#define FL_BMCOLOR 520
static void
show_map_unit(float mx, float my)
{
fl_set_input(mxi, ftoa(mx, 5));
fl_set_input(myi, ftoa(my, 5));
}
/*********************************************************************
* report distance from the origin: Here xx & yy are the mouse position
* relative to window.
*********************************************************************/
#include <math.h>
static void
report_distance(int xx, int yy)
{
float dx, dy;
fl_freeze_form(tobj);
if (pixels)
{ /* absolute coordinates */
fl_set_input(ix, itoa((xx - orix)));
fl_set_input(iy, itoa((yy - oriy)));
dx = (xx - orix);
dy = (yy - oriy);
}
else
{ /* user coord */
dx = mapx * (xx - orix);
dy = mapy * (yy - oriy);
fl_set_input(ix, ftoa(dx, 5));
fl_set_input(iy, ftoa(dy, 5));
}
fl_unfreeze_form(tobj);
if (reportr)
fl_set_object_label(dtext, ftoa(sqrt(dx * dx + dy * dy), 2));
}
/*************************************************************
* Show object in current selected units
************************************************************/
static void
report_size(int width, int height)
{
fl_freeze_form(tobj);
if (pixels)
{
fl_set_slider_value(sl[0], width);
fl_set_slider_value(sl[1], height);
}
else
{
fl_set_slider_value(sl[0], mapx * width);
fl_set_slider_value(sl[1], mapy * height);
}
fl_unfreeze_form(tobj);
}
/*********************************************************************
* draw the object in normal buffer, relative to image, in units of pixels
*
**********************************************************************/
static void
mark_doit(IPTR im, int xx, int yy, int ww, int hh)
{
long owin = winget();
rgba_t cc = Pack(dcol[0], dcol[1], dcol[2]);
int bx, by, bw, bh, halflw;
set_current_window(win_id);
drawmode(NORMALDRAW);
reshapeviewport();
linewidth(lwidth);
smooth_line_on(im, dcol, lwidth);
cdraw(xx, yy, ww, hh, cfill, angle);
#ifndef SGL_BUF
if (doublebuffer)
{
swapbuffers();
cdraw(xx, yy, ww, hh, cfill, angle);
}
#endif
if (immediate)
{
/* if immediate, read the framebuffer */
halflw = (lwidth) / 2;
find_bbox(xx - halflw, yy - halflw, ww + lwidth, hh + lwidth,
0.1 * angle, &bx, &by, &bw, &bh);
bx -= halflw;
by -= halflw;
bw += lwidth;
bh += lwidth;
fb_to_ras(im, make_rect(bx, by, bw, bh));
}
else
{
/* save current figure */
save_it(currentobj, xx - im->xi, yy - im->yi, ww, hh,
lwidth, cc, dcol[3]);
}
smooth_line_off(im, dcol);
clear_over_pup();
set_current_window(owin);
}
/* A dummy function to get call back prototype right */
/* ARGSUSED */
static void
doit(FL_OBJECT * ob, long p)
{
int xx = x, yy = y;
mark_doit(imgptr, xx, yy, w, h);
}
/******************************************************
* User input for units
******************************************************/
#include <stdlib.h>
static void
map_cb(FL_OBJECT * ob, long p)
{
const char *q = fl_get_input(ob);
float tmp;
if (p == 1)
{
if ((tmp = atof(q)) <= 0.0)
{
fl_set_input(ob, ftoa(mapx, 5));
tmp = mapx;
}
mapx = tmp;
}
else
{
if ((tmp = atof(q)) <= 0.0)
{
fl_set_input(ob, ftoa(mapy, 5));
tmp = mapy;
}
mapy = tmp;
}
if (!pixels)
map_slider();
report_distance(x, y);
}
/***************************************************************
* With the given units and MAXOBJSIZE, set the slider
***************************************************************/
#include <math.h>
static void
map_slider(void)
{
int xp, yp;
fl_freeze_form(tobj);
if (!pixels)
{ /* use user coordinates system */
xp = (mapx < 1.0) ? -(log10(mapx) - 0.95) : 0;
yp = (mapy < 1.0) ? -(log10(mapy) - 0.95) : 0;
fl_set_slider_precision(sl[0], xp);
fl_set_slider_precision(sl[1], yp);
fl_set_slider_step(sl[0], mapx);
fl_set_slider_step(sl[1], mapy);
fl_set_slider_bounds(sl[0], 0.0, (mapx * MAXOSIZE));
fl_set_slider_bounds(sl[1], 0.0, (mapy * MAXOSIZE));
fl_set_slider_value(sl[0], (mapx * w));
fl_set_slider_value(sl[1], (mapy * h));
}
else
{
fl_set_slider_precision(sl[0], 0);
fl_set_slider_precision(sl[1], 0);
fl_set_slider_step(sl[0], 1);
fl_set_slider_step(sl[1], 1);
fl_set_slider_bounds(sl[0], 0.0, MAXOSIZE);
fl_set_slider_bounds(sl[1], 0.0, MAXOSIZE);
fl_set_slider_value(sl[0], w);
fl_set_slider_value(sl[1], h);
}
fl_unfreeze_form(tobj);
}
/***************************************************************
* A new location is input from keyboard
**************************************************************/
static void
position_cb(FL_OBJECT * ob, long p)
{
const char *q = fl_get_input(ob);
float xx, yy;
if (p == 0)
{
xx = atof(q);
x = pixels ? (xx + 0.5) : (xx / mapx + 0.5);
x += orix;
}
else
{
yy = atof(q);
y = pixels ? (yy + 0.5) : (yy / mapy + 0.5);
y += oriy;
}
mark_draw(currentobj, bcolor);
}
/*********************************************************************
* Since bcolor is an index in over/pup plane and we will map it
* to different colors, better save it
*******************************************************************/
static short bc[3];
static void
save_bcolor(void)
{
switch_frame_buffer();
getmcolor(bcolor, bc, bc + 1, bc + 2);
/* default drawing color */
mapcolor(bcolor, dcol[0], dcol[1], dcol[2]);
drawmode(NORMALDRAW);
}
static void
restore_bcolor(void)
{
switch_frame_buffer();
mapcolor(bcolor, bc[0], bc[1], bc[2]);
drawmode(NORMALDRAW);
}
/* ARGSUSED */
static void
handle_bmcb(FL_OBJECT * ob, long p)
{
static int last = -1;
if (last >= 0)
{
fl_set_object_color(bms[last], FL_BLACK, FL_MAGIC1);
fl_redraw_object(bms[last]);
}
last = p;
fl_set_object_color(bms[p], FL_BMCOLOR, FL_MAGIC2);
fl_redraw_object(bms[p]);
complete_draw(p + offset, bcolor);
}
/******************************************************************/
/* routines related to saving and displaying by other routines */
typedef struct
{
int obj; /* index into the struct */
int x, y, w, h, t; /* dimensions */
int angle; /* in tenth of degrees */
rgba_t color; /* color of obj */
ci_t ci; /* color index */
}
Save_obj;
static int totalsave;
/*
* by defining saveobj to be pointers, we can save about 20 bytes each, or
* MAXSAVE * 20, or 2K, not worth it
*/
static Save_obj saveobj[MAXSAVE];
/****************************************************************
* Save current objects
****************************************************************/
static void
save_it(int ind, int cx, int cy, int cw, int ch, int t,
rgba_t c, ci_t ci)
{
Save_obj *p = saveobj + totalsave;
p->obj = ind;
p->x = cx;
p->y = cy;
p->w = cw;
p->h = ch;
p->color = c;
p->ci = ci;
p->t = t;
p->angle = angle;
if (++totalsave >= MAXSAVE)
totalsave = MAXSAVE - 1;
}
/**************************************************************
* Global routine to display all saved SGFs
*************************************************************/
void
display_sgf(IPTR im)
{
long owin;
Save_obj *p = saveobj, *ps;
const Obj_t *ob;
int xi, yi;
int olwidth = lwidth;
int cc[4];
if (!totalsave || !im || !im->ok)
return;
owin = winget();
set_current_window(win_id);
reshapeviewport();
xi = im->xi;
yi = im->yi;
/*
* it is sort of bad that we have to turn anti-aliasing on and off, but
* have no choice lwidth != 1 does not work right
*/
for (ps = p + totalsave; p < ps; p++)
{
set_current_window(win_id);
linewidth(p->t);
lwidth = p->t;
cc[4] = p->ci;;
Unpack(p->color, cc[0], cc[1], cc[2]);
smooth_line_on(im, cc, lwidth);
ob = objs + p->obj;
ob->how(p->x + xi, p->y + yi, p->w, p->h, ob->fill, p->angle);
smooth_line_off(im, cc);
}
/* must restore width to 1 */
linewidth(1);
set_current_window(owin);
lwidth = olwidth;
}
/*********************************************************************
* Write to and Read from disk the sgf
*********************************************************************/
void
dump_sgf(FILE * fp)
{
Save_obj *p = saveobj, *ps;
fprintf(fp, "#SG %d\n", totalsave);
fputs("Obj x y w h t r g b ci rot. Note (x,y) refers sgf's center\n", fp);
for (ps = p + totalsave; p < ps; p++)
{
fprintf(fp, "#%s %d %d %d %d %d\n", objs[p->obj].name,
p->x, p->y, p->w, p->h, p->t);
fprintf(fp, "%g %g %g %d \n", C2NC(get_R(p->color)),
C2NC(get_G(p->color)), C2NC(get_B(p->color)), (int) p->ci);
fprintf(fp, "%d \n", p->angle);
}
}
/**********************************************************************
* Read in SGFs written by dump_sgf
**********************************************************************/
void
load_sgf(IPTR im)
{
int n, r, g, b, ci;
Save_obj *p = saveobj + totalsave, *ps;
char buf[100], nm[40];
FILE *fp = im->fp;
/* by using this, we can change Save_obj freely */
int hx, hy, hw, hh, ht;
while ((n = getc(fp)) != EOF && n != '#')
;
if (n != '#' || (n = getc(fp)) != 'S' || (n = getc(fp)) != 'G')
return;
n = readint(fp);
if (n <= 0)
return;
if (n >= MAXSAVE)
{
Bark("LoadSgf", "Too many of them. Keeping %d", MAXSAVE);
n = MAXSAVE;
return;
}
M_info("LoadSGF", "Total %d sgfs found", n);
for (ps = p + n; p < ps; p++)
{
while (fgets(buf, sizeof(buf) - 1, fp) && buf[0] != '#')
;
if (buf[0] != '#') /* premature EOF */
break;
sscanf(buf + 1, "%s %d %d %d %d %d", nm, &hx, &hy, &hw, &hh, &ht);
p->x = hx;
p->y = hy;
p->w = hw;
p->h = hh;
p->t = ht;
r = (readfloat(fp) * PCMAXV + 0.4);
g = (readfloat(fp) * PCMAXV + 0.4);
b = (readfloat(fp) * PCMAXV + 0.4);
p->color = Pack(r, g, b);
ci = readpint(fp);
p->ci = ci;
if (ci < 0 || ci >= MAXCML)
p->ci = 0;
p->angle = readint(fp);
p->obj = sgf_get_index(nm);
}
totalsave += n;
}
/********************************************************************
* we only need to take care the RGB case because colormapped case
* will be taken care of automatically by system colormap
********************************************************************/
void
sgf_to_gray(void)
{
register int q;
register Save_obj *p = saveobj, *ps;
for (ps = p + totalsave; p < ps; p++)
{
q = cpack2gray(p->color);
p->color = Pack(q, q, q);
}
}
/* take care of from RGB -> ci */
void
sgf_to_cmap(void)
{
register Save_obj *p = saveobj, *ps;
if (!IS_CI(imgptr))
return;
for (ps = p + totalsave; p < ps; p++)
p->ci = cmap_closematch(imgptr->cmap,
get_R(p->color), get_G(p->color), get_B(p->color));
}
void
del_marking(void)
{
totalsave = 0;
return;
}
/*********************************************************
* Routines to get info for format capable of vectors
*************************************************************/
int
number_of_sgf(void)
{
return totalsave;
}
const char *
sgf_name(int n)
{
return (saveobj[n].obj + objs)->name;
}
const char *
sgf_psdraw(int n)
{
return (saveobj[n].obj + objs)->psdraw;
}
/******************************************************************
* important info about an sgf: (x,y), (w,h), line width, closed path
* and rotation angle
*******************************************************************/
void
get_sgf_info(int n, int *xl, int *yl,
int *wd, int *ht, int *t, int *fi, int *a)
{
Save_obj *p = saveobj + n;
if (n < 0 || n >= totalsave)
return;
*xl = p->x;
*yl = p->y;
*wd = p->w;
*ht = p->h;
*t = p->t;
*a = (0.1 * p->angle);
*fi = ((objs + saveobj[n].obj)->fill) != 0;
}
/*********************************************************************
* in order to find the bounding box correctly, we need info about the
* dimensions of all sgfs that sticks out of the image. Only return the abs
* value of the portion that sticks out. Rotation is not considered which
* could cause some error, but typically sgf's are small enuf to ignore it.
*********************************************************************/
void
get_sgf_bounds(IPTR im, int *top, int *left, int *bottom, int *right)
{
Save_obj *p = saveobj, *ps;
int l = 0, b = 0, r = im->w, t = im->h;
int w2, h2;
for (ps = p + totalsave; p < ps; p++)
{
h2 = p->h / 2;
w2 = p->w / 2;
if (l > p->x - w2)
l = p->x - w2;
if (b > p->y - h2)
b = p->y - h2;
if (r < p->x + w2)
r = p->x + w2;
if (t < p->y + h2)
t = p->y + h2;
}
/* return abs */
*left = -l;
*bottom = -b;
*right = r - im->w;
*top = t - im->h;
}
void
get_sgf_color(int n, int *r, int *g, int *b)
{
int i;
if (!imgptr)
return;
if (IS_CI(imgptr))
{
i = saveobj[n].ci;
*r = imgptr->cmap->ct[0][i];
*g = imgptr->cmap->ct[1][i];
*b = imgptr->cmap->ct[2][i];
}
else
{
Unpack(saveobj[n].color, *r, *g, *b);
}
}
/* ARGSUSED */
static void
del_dummy(FL_OBJECT * p, long q)
{
del_marking();
imgptr->io->display(imgptr, 0, 1);
}
/*******************************************************************
* Flip thru all defined objects.
* Should never been called if obj is less than that can be shown
********************************************************************/
/* ARGSUSED */
static void
more_cb(FL_OBJECT * ob, long p)
{
int i;
if (offset + totalshown < totalobjs)
offset += totalshown;
else if (offset >= totalshown)
offset -= totalshown;
fl_freeze_form(tobj);
for (i = 0; i < totalshown && i + offset < totalobjs; i++)
{
fl_show_object(bms[i]);
fl_activate_object(hb[i]);
if (i + offset != currentobj)
fl_set_object_color(bms[i], FL_BLACK, FL_MAGIC1);
else
fl_set_object_color(bms[i], FL_BMCOLOR, FL_MAGIC2);
fl_set_bitmap(bms[i], BM_W, BM_H, objs[i + offset].bits);
}
for (; i < totalshown; i++)
{
fl_hide_object_only(bms[i]);
fl_deactivate_object(hb[i]);
}
fl_unfreeze_form(tobj);
}
/*****************************************************
* aspect ratio and coordinate system switch
******************************************************/
static void
misc_cb(FL_OBJECT * ob, long p)
{
if (p == 2)
{ /* aspect ration of obj */
xy = fl_get_choice(ob) - 1;
}
else
{
pixels = fl_get_choice(ob) - 1;
map_slider();
report_distance(x, y);
}
}
/* ARGSUSED */
static void
dist_cb(FL_OBJECT * ob, long p)
{
reportr = fl_get_button(ob);
}
/****************************************************************
* Set origin of measurement
***************************************************************/
/* ARGSUSED */
static void
origin_cb(FL_OBJECT * ob, long p)
{
char ori[50];
/* get the current position in pixels */
orix = x;
oriy = y;
sprintf(ori, "%d,%d", orix, oriy);
fl_set_object_label(otext, ori);
report_distance(x, y);
}
/*******************************************************************
* Select rendering method
******************************************************************/
/*ARGSUSED*/
static void
mode_cb(FL_OBJECT * ob, long q)
{
immediate = fl_get_choice(ob) - 1;
}
/*************************************************************
* What to do if different color is requested
*************************************************************/
static void
handle_color_change(int c[])
{
int i = currentobj - offset;
switch_frame_buffer();
/* need not change the drawing because it is always in colormap mode */
mapcolor(bcolor, c[0], c[1], c[2]);
/* take care of bitmaps */
drawmode(NORMALDRAW);
/* if visible: i is the index, offset the starting point */
if (i >= 0 && i < totalshown)
{
fl_mapcolor(FL_BMCOLOR, c[0], c[1], c[2]);
fl_redraw_object(bms[i]);
}
}
/*************************************************************
* Do this when color change is requested
************************************************************/
/*ARGSUSED */
static void
color_cb(FL_OBJECT * ob, long p)
{
set_getcolor_cb(handle_color_change);
/* non block */
get_color(imgptr, dcol, 0);
}
/**************************************************************
* Change line thickness: look bad if not line
*************************************************************/
/*ARGSUSED*/
static void
thickness_cb(FL_OBJECT * ob, long p)
{
int status;
do
{
status = getint("Enter line thickness", &lwidth, 1, 50, 1);
set_current_window(win_id);
switch_frame_buffer();
color(0);
cdraw(x, y, w, h, cfill, angle);
color(bcolor);
linewidth(lwidth);
cdraw(x, y, w, h, cfill, angle);
}
while (status == 0);
mark_draw(currentobj, bcolor);
}
/****************************************************************
* Change object size: if aspect ratio is to be kept, changing
* x size should automatically set y size and vice versa
****************************************************************/
static void
size_cb(FL_OBJECT * ob, long p)
{
float sx, sy;
if (p == 0) /* xsize */
{
sx = fl_get_slider_value(ob);
if (xy)
fl_set_slider_value(sl[1], sy = sx);
else
sy = fl_get_slider_value(sl[1]);
}
else
{
sy = fl_get_slider_value(ob);
if (xy)
fl_set_slider_value(sl[!p], sx = sy);
else
sx = fl_get_slider_value(sl[!p]);
}
/* if in user coordinates, convert to pixels */
if (!pixels)
{
w = (sx / mapx + 0.5);
h = (sy / mapy + 0.5);
}
else
{
w = (sx + 0.4);
h = (sy + 0.4);
}
/* always show it in pixels */
mark_draw(currentobj, bcolor);
show_rect_size(w, h);
}
static void
report_rotation(float f)
{
fl_set_object_label(rtext, ftoa(f, 1));
}
/*****************************************************
* get rotation angle in deci-degrees
*****************************************************/
/* ARGSUSED */
static void
rotate_cb(FL_OBJECT * ob, long q)
{
while (!get_orientation("Enter Rotation", &angle, 1))
{
if (langle - angle)
{
mark_draw(currentobj, bcolor);
}
}
fl_set_object_label(rtext, ftoa(0.1 * angle, 1));
mark_draw(currentobj, bcolor);
}
/*ARGSUSED*/
static void
mark_done(FL_OBJECT * ob, long q)
{
fl_qenter(KEYBD, 27);
}
/********************************************************************
* The form
*******************************************************************/
static void
create_form_tobj(void)
{
FL_OBJECT *obj;
float xx, dx, yy, dy, x0;
int i, j, k, ncol;
static int ok;
if (ok)
return; /* initialize static variables */
fl_mapcolor(FL_BMCOLOR, dcol[0], dcol[1], dcol[2]);
switch_frame_buffer();
mapcolor(bcolor, dcol[0], dcol[1], dcol[2]);
drawmode(NORMALDRAW);
tobj = fl_bgn_form(FL_NO_BOX, 250.0, 310.0);
obj = fl_add_box(FL_UP_BOX, 0.0, 0.0, 250.0, 310.0, "");
obj = fl_add_button(FL_HB, 0.0, 0.0, 250.0, 310.0, "");
fl_set_call_back(obj, help_cb, HELP_MARKING);
obj = fl_add_box(FL_BORDER_BOX, 10.0, 40.0, 225.0, 110.0, "");
/* the origin setting and misc control group */
fl_bgn_group();
x = 18.0;
y = 208.0;
dx = 70.0;
dy = 23.0;
obj = fl_add_box(FL_BORDER_BOX, 10.0, 155.0, 228.0, 80.0, "");
obj = fl_add_button(FL_NB, x, y, dx, dy, "SetOrigin");
fl_set_object_boxtype(obj, FL_ROUNDED_BOX);
fl_set_object_lsize(obj, 10.0);
fl_set_object_color(obj, FL_MAGIC1, FL_YELLOW);
fl_set_call_back(obj, origin_cb, 0);
obj = fl_add_button(FL_NB, x + dx, y, dx, dy, "Rotate");
fl_set_object_boxtype(obj, FL_ROUNDED_BOX);
fl_set_object_lsize(obj, 10.0);
fl_set_object_color(obj, FL_MAGIC1, FL_YELLOW);
fl_set_call_back(obj, rotate_cb, 0);
obj = fl_add_button(FL_PB, x + 2 * dx, y, dx, dy, "DReport");
fl_set_object_boxtype(obj, FL_ROUNDED_BOX);
fl_set_object_color(obj, FL_MAGIC1, FL_YELLOW);
fl_set_object_lsize(obj, 10.0);
fl_set_call_back(obj, dist_cb, 0);
y -= dy + 1;
otext = obj = fl_add_text(FL_NT, x, y, dx, 20.0, "");
fl_set_object_boxtype(obj, FL_ROUNDED_BOX);
fl_set_object_lsize(obj, 10.0);
fl_set_object_align(obj, FL_ALIGN_CENTER);
rtext = obj = fl_add_text(FL_NT, x + dx, y, dx, 20.0, "0");
fl_set_object_boxtype(obj, FL_ROUNDED_BOX);
fl_set_object_lsize(obj, 10.0);
fl_set_object_align(obj, FL_ALIGN_CENTER);
dtext = obj = fl_add_text(FL_NT, x + 2.0 * dx, y, dx, 20.0, "0");
fl_set_object_boxtype(obj, FL_ROUNDED_BOX);
fl_set_object_lsize(obj, 10.0);
fl_set_object_align(obj, FL_ALIGN_CENTER);
y = 158.0;
dx = 70;
dy = 23;
/* coordinate system to use */
obj = fl_add_choice(FL_NC, x, y, dx, dy, "");
fl_set_object_boxtype(obj, FL_ROUNDED_BOX);
fl_set_choice_fontsize(obj, 10.0);
fl_addto_choice(obj, "User");
fl_addto_choice(obj, "Pixels");
fl_set_choice(obj, pixels + 1);
fl_set_call_back(obj, misc_cb, 0);
x += dx;
/* mode of operation */
obj = fl_add_choice(FL_NC, x, y, dx, dy, "");
fl_set_object_boxtype(obj, FL_ROUNDED_BOX);
fl_set_choice_fontsize(obj, 10.0);
fl_addto_choice(obj, "Deferred");
fl_addto_choice(obj, "Immediate");
fl_set_choice(obj, immediate + 1);
fl_set_call_back(obj, mode_cb, 0);
/* aspect ratio */
x += dx;
obj = fl_add_choice(FL_NC, x, y, dx, dy, "");
fl_set_object_boxtype(obj, FL_ROUNDED_BOX);
fl_set_choice_fontsize(obj, 10.0);
fl_addto_choice(obj, "FreeASP");
fl_addto_choice(obj, "KeepASP");
fl_set_choice(obj, xy + 1);
fl_set_call_back(obj, misc_cb, 2);
fl_end_group();
/* input group */
ingrp = fl_bgn_group();
ix = obj = fl_add_input(FL_FLOAT_INPUT, 35.0, 70.0, 60.0, 20.0, "X:");
fl_set_object_boxtype(obj, FL_FRAME_BOX);
fl_set_object_color(obj, 47, 51);
fl_set_object_lsize(obj, 10.0);
fl_set_call_back(obj, position_cb, 0);
iy = obj = fl_add_input(FL_FLOAT_INPUT, 35.0, 50.0, 60.0, 20.0, "Y:");
fl_set_object_boxtype(obj, FL_FRAME_BOX);
fl_set_object_color(obj, 47, 51);
fl_set_object_lsize(obj, 10.0);
fl_set_call_back(obj, position_cb, 1);
fl_end_group();
fl_bgn_group();
mxi = obj = fl_add_input(FL_FLOAT_INPUT, 135.0, 70.0, 70.0, 20.0, "Mx");
fl_set_object_boxtype(obj, FL_FRAME_BOX);
fl_set_object_color(obj, 47, 51);
fl_set_object_lsize(obj, 10.0);
fl_set_object_align(obj, FL_ALIGN_RIGHT);
fl_set_input(obj, "1.0");
fl_set_call_back(obj, map_cb, 0);
myi = obj = fl_add_input(FL_FLOAT_INPUT, 135.0, 50.0, 70.0, 20.0, "My");
fl_set_object_boxtype(obj, FL_FRAME_BOX);
fl_set_object_color(obj, 47, 51);
fl_set_object_lsize(obj, 10.0);
fl_set_object_align(obj, FL_ALIGN_RIGHT);
fl_set_input(obj, "1.0");
fl_set_call_back(obj, map_cb, 1);
obj = fl_add_button(FL_NORMAL_BUTTON, 95.0, 50.0, 40.0, 40.0, "OK");
fl_set_object_boxtype(obj, FL_FRAME_BOX);
fl_set_object_color(obj, 47, 9);
fl_set_button_shortcut(obj, "po");
fl_set_call_back(obj, doit, 0);
fl_end_group();
sl[0] = obj = fl_add_valslider(FL_HNS, 15.0, 120.0, 150.0, 20.0, "");
fl_set_object_boxtype(obj, FL_BORDER_BOX);
fl_set_object_color(obj, 47, 1);
fl_set_object_lsize(obj, 10.0);
fl_set_slider_bounds(obj, 1.0, MAXOSIZE);
fl_set_slider_step(obj, 1.0);
fl_set_slider_precision(obj, 0);
fl_set_slider_value(obj, h);
fl_set_call_back(obj, size_cb, 0);
sl[1] = obj = fl_add_valslider(FL_HNS, 15.0, 100.0, 150.0, 20.0, "");
fl_set_object_boxtype(obj, FL_BORDER_BOX);
fl_set_object_color(obj, 47, 1);
fl_set_object_lsize(obj, 10.0);
fl_set_slider_bounds(obj, 1.0, MAXOSIZE);
fl_set_slider_step(obj, 1.0);
fl_set_slider_precision(obj, 0);
fl_set_slider_value(obj, w);
fl_set_call_back(obj, size_cb, 1);
obj = fl_add_button(FL_NB, 170.0, 120.0, 60.0, 20.0, "Color");
fl_set_object_boxtype(obj, FL_FRAME_BOX);
fl_set_object_color(obj, 47, 4);
fl_set_object_lsize(obj, 10.0);
fl_set_call_back(obj, color_cb, 0);
obj = fl_add_button(FL_NB, 170.0, 100.0, 60.0, 20.0, "Lwidth");
fl_set_object_boxtype(obj, FL_FRAME_BOX);
fl_set_object_color(obj, 47, 9);
fl_set_object_lsize(obj, 10.0);
fl_set_call_back(obj, thickness_cb, 0);
/*
* The bitmap groups max nine per row, could be seven, depending on
* totalobjs
*/
obj = fl_add_box(FL_BORDER_BOX, 8.0, 240.0, 230, 60.0, "");
if (totalobjs < 18) /* 9 per row */
ncol = 9;
else
{
ncol = 7;
obj = fl_add_button(FL_NB, 230 - 40, 230, 45, 55, "More");
fl_set_object_lsize(obj, 10.0);
fl_set_call_back(obj, more_cb, 0);
}
dx = dy = 25;
yy = 270.0;
x0 = xx = 10;
totalshown = ncol * 2;
fl_bgn_group();
for (i = k = 0; i < totalshown; i += ncol, xx = x0, yy -= dy)
{
for (j = 0; j < ncol; j++, xx += dx, k++)
{
if (k >= totalobjs)
continue;
bms[k] = obj = fl_add_bitmap(FL_NBM, xx, yy, dx, dy, "");
fl_set_object_boxtype(obj, FL_FRAME_BOX);
fl_set_bitmap(bms[k], BM_W, BM_H, objs[k].bits);
hb[k] = obj = fl_add_button(FL_HB, xx, yy, dx, dy, "");
fl_set_call_back(obj, handle_bmcb, k);
}
}
totalshown = k;
fl_end_group();
obj = fl_add_button(FL_NB, 10.0, 10.0, 70.0, 25.0, "DelAll");
fl_set_object_lsize(obj, 10.0);
fl_set_call_back(obj, del_dummy, 0);
obj = fl_add_button(FL_NB, 163.0, 10.0, 70.0, 25.0, "Done");
fl_set_object_lsize(obj, 10.0);
fl_set_call_back(obj, mark_done, 0);
fl_end_form();
fl_scale_form(tobj, 1.2, 1.1);
ok = 1;
}